--[[ 打击者1945二代脚本,作用是显示坐标和在坐标位置显示十字框和中心红色方块
  十字框有蓄力显示的效果
  可作为彩京等stg游戏的模版,只要坐标是正常显示的就行
  
  这里有个大坑!难怪FBNEO不支持!我结合现有的作弊码判断坐标地址的范围,
  再用cheatEngine找到了坐标,却发现模拟器的内存映射地址顺序与实际
  内存地址(就是cheatEngine找到的地址)有不同,估计是MAME把人家的大端
  改成了小端,所以在MAME中,y轴的高位地址币低位小1,但在cheatEngine找到
  的实际地址其实是大1!这个大坑折腾了我好一阵!
  
  By setycyas @2025-02-04
]]

-- 这里设定基本参数
local GAME = {
  -- 分辨率
  X_RESOLUTION = 224,
  Y_RESOLUTION = 320,
  -- 横坐标只需要低位,纵坐标用read_u16读取,需要从高位读起
  X_ADDR = 0x60103a5,
  Y_ADDR = 0x60103a8,
  -- 火力与蓄力地址
  POW_ADDR = 0x60103E7,
  CHARGE_ADDR = 0x6010414,
  -- 显示方块的半长半高,单位为MAME的屏幕比例
  BOX_HALF_WIDTH = 0.0065,
  BOX_HALF_HEIGHT = 0.006,
  -- 为看得更清楚,再画两个较大的长方体
  XBOX_HALF_WIDTH = 0.032,
  XBOX_HALF_HEIGHT = 0.0065,
  YBOX_HALF_WIDTH = 0.0065,
  YBOX_HALF_HEIGHT = 0.035,
  YBOX_OFFSET = 0.005,
  -- 像素平移
  X_OFFSET = -1,
  Y_OFFSET = 0,
  -- 蓄力情况不同的颜色
  CHARGE_COLOR0 = 0xDDaaaaaa,
  CHARGE_COLOR1 = 0xDD0000ff,
  CHARGE_COLOR2 = 0xDDffd700,
  -- 蓄力等级需要的数值
  CHARGE_LV1 = 4,
  CHARGE_LV2 = 13,
  -- mame api用的对象
  mem = manager.machine.devices[':maincpu'].spaces['program'],
  container = manager.machine.screens[":screen"].container,
  ui_container = manager.machine.render.ui_container,
}

-- 刷新设备,成功获取设备返回true,否返回false
function GAME.refreshDevices()
  GAME.mem = manager.machine.devices[':maincpu'].spaces['program']
  GAME.container = manager.machine.screens[":screen"].container
  GAME.ui_container = manager.machine.render.ui_container
  
  if (GAME.mem and GAME.container and GAME.ui_container) then
    return true
  else
    return false
  end
end

-- 坐标变换函数,从得到的坐标变为屏幕显示位置(是个比例),返回0.0-1.0的浮点数,
-- 后期游戏可能很复杂,需要根据游戏的情况手动操作变化
function GAME.getX()
  local xlow
  xlow =  1.0*GAME.mem:read_u8(GAME.X_ADDR)
  return (xlow+GAME.X_OFFSET)/GAME.X_RESOLUTION
end
function GAME.getY()
  local yword -- 2字节所以叫word
  yword =  1.0*GAME.mem:read_u16(GAME.Y_ADDR)
  return (yword+GAME.Y_OFFSET)/GAME.Y_RESOLUTION
end

-- 数据显示
function GAME.showInfo(GAMEList ,position, color)
  
  for index, value in ipairs(GAMEList) do
    GAME.ui_container:draw_text(position, 0.05*index, value, color)
  end
  
end

-- 显示监视的数据
function GAME.check()
  local power
  power = GAME.mem:read_u8(GAME.POW_ADDR)
  GAME.container:draw_text(0, 0, "P="..power, 0xFF005500, 0xFFcccccc)
  end

-- 显示辅助线
function GAME.showAssist()
  GAME.ui_container:draw_box(0.495, 1.0, 0.505, 0.96, 0xDDdd00dd, 0xDDdd00dd)
end

-- 显示方块,x,y是浮点数坐标
function GAME.showSqua(x, y)
  local container, charge, chargeColor
  container = GAME.container
  charge = GAME.mem:read_u8(GAME.CHARGE_ADDR)
  -- 根据蓄力情况获取颜色
  if (charge < GAME.CHARGE_LV1) then
    chargeColor = GAME.CHARGE_COLOR0
  elseif (charge < GAME.CHARGE_LV2) then
    chargeColor = GAME.CHARGE_COLOR1
  else
    chargeColor = GAME.CHARGE_COLOR2
  end
    
  if (x > 0.0) and (y > 0.0) then
    -- 十字框
    container:draw_box(
      y-GAME.XBOX_HALF_HEIGHT,
      x-GAME.XBOX_HALF_WIDTH,
      y+GAME.XBOX_HALF_HEIGHT,
      x+GAME.XBOX_HALF_WIDTH,
      0xFFFF00FF, chargeColor
    )
  
    container:draw_box(
      y-GAME.YBOX_HALF_HEIGHT-GAME.YBOX_OFFSET,
      x-GAME.YBOX_HALF_WIDTH,
      y+GAME.YBOX_HALF_HEIGHT-GAME.YBOX_OFFSET,
      x+GAME.YBOX_HALF_WIDTH,
      0xFFFF00FF, chargeColor
    )
    -- 中心
    container:draw_box(
      y-GAME.BOX_HALF_HEIGHT,
      x-GAME.BOX_HALF_WIDTH,
      y+GAME.BOX_HALF_HEIGHT,
      x+GAME.BOX_HALF_WIDTH,
      0xFFFF0000, 0xFFFF0000
    )
  end
  
end

-- 主函数,绑定后每一帧执行一次该函数
function GAME.main()
  local x, y
  
  -- 刷新设备,并判断当前帧能否操作
  if (not GAME.refreshDevices()) then
    return
  end

  x = GAME.getX()
  y = GAME.getY()
  
  -- 显示监视数据
  --GAME.showInfo({power, charge}, 0.05, 0xFF00ff00)
  -- 辅助线
  GAME.showAssist()
  -- 数据监视
  GAME.check()
  -- 显示角色中心方块
  GAME.showSqua(x, y)

end

-- 绑定每一帧执行的函数
emu.register_frame_done(GAME.main, "frame")
-- 导出到全局变量
_G.game = GAME

return GAME